There's a very subtle problem with using raw built-in arrays. Consider this:
void f(Base* array_of_Base)
{
array_of_Base[3].memberfn();
}
main()
{
Derived array_of_Derived[10];
f(array_of_Derived);
}
This is perfectly type-safe, since a D* is-a B*, but it is horrendously evil, since Derived might be larger than Base, so the array index in f() not only isn't type safe, it's not even going to be pointing at a real object! In general it'll be pointing somewhere into the innards of some poor D.
The fundamental problem here is that C++ cannot distinguish a ptr-to-a-thing from a ptr-to-an-array-of-things (witness the required '[]' in 'delete[]' when deleting an array as another example of how these different kinds of ptrs are actually different). Naturally C++ 'inherited' this feature from C.
This underscores the advantage of using an array-like *class* instead of using a raw array (the above problem would have been properly trapped as an error if we had used a 'Vec<T>' rather than a 'T[]'; ex: you cannot pass a Vec<Derived> to 'f(Vec<Base>& v)').